﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;

namespace Compiler
{
    class SetEqualityComparer<ItemType, ItemComparer> 
        : IEqualityComparer<HashSet<ItemType>> 
        where ItemComparer : IEqualityComparer<ItemType>, new()
    {
        IEqualityComparer<ItemType> itemComparer = new ItemComparer();

        public bool Equals(HashSet<ItemType> x, HashSet<ItemType> y)
        {
            if (x.Count != y.Count)
                return false;
            if (x.Comparer.GetType() == itemComparer.GetType())
                return x.SetEquals(y);
            if (y.Comparer.GetType() == itemComparer.GetType())
                return y.SetEquals(x);

            return new HashSet<ItemType>(x, itemComparer).SetEquals(y);
            
            //return !x.Except(y, itemComparer).Any(); //langsame linq-lösung. wirklich langsamer als new HashSet + SetEquals? -> Testen
        }

        public int GetHashCode(HashSet<ItemType> obj)
        {
            int hash = 0;
            foreach (var item in obj)
                hash += itemComparer.GetHashCode(item);

            return hash;
        }
    }
    
    ////mit ko-/kontravarianz wäre das wohl unnötig.
    //class SetSetEqualityComparer<SetCmp, ItemType> 
    //    : IEqualityComparer<HashSet<HashSet<ItemType>>> 
    //    where SetCmp : IEqualityComparer<HashSet<ItemType>>, new ()
    //{
    //    IEqualityComparer<HashSet<ItemType>> setCmp = new SetCmp();

    //    public bool Equals(HashSet<HashSet<ItemType>> x, HashSet<HashSet<ItemType>> y)
    //    {
    //        if (x.Count != y.Count)
    //            return false;
    //        if (x.Comparer.GetType() == setCmp.GetType())
    //            return x.SetEquals(y);
    //        if (y.Comparer.GetType() == setCmp.GetType())
    //            return y.SetEquals(x);

    //        return new HashSet<HashSet<ItemType>>(x, setCmp).SetEquals(y);
    //    }

    //    public int GetHashCode(HashSet<HashSet<ItemType>> obj)
    //    {
    //        int hash = 0;
    //        foreach (var item in obj)
    //            hash += setCmp.GetHashCode(item);

    //        return hash;
    //    }
    //}
}
